Skip to content

fix: check agent server readiness timeout return value (fixes #1631)#1655

Merged
MervinPraison merged 3 commits into
mainfrom
claude/issue-1631-20260507-0942
May 13, 2026
Merged

fix: check agent server readiness timeout return value (fixes #1631)#1655
MervinPraison merged 3 commits into
mainfrom
claude/issue-1631-20260507-0942

Conversation

@MervinPraison
Copy link
Copy Markdown
Owner

@MervinPraison MervinPraison commented May 12, 2026

Fixes #1631

Summary

This PR fixes a silent failure mode in the agent server startup process where ready_event.wait(timeout=5.0) return values were ignored, causing difficult-to-debug failures when servers didn't start within the timeout period.

Changes

  • βœ… Check return value from ready_event.wait() to detect timeouts
  • βœ… Log descriptive warning when server doesn't become ready
  • βœ… Make timeout configurable via PRAISONAI_SERVER_READY_TIMEOUT env var
  • βœ… Add comprehensive regression tests

Testing

  • Added unit tests in tests/unit/agents/test_server_registry_timeout.py
  • Tests cover timeout scenarios, environment variable configuration, and success cases

Backward Compatibility

  • Fully backward compatible - no behavior changes for successful server startups
  • Only adds helpful logging for previously silent failure cases

Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Server readiness timeout is now configurable via PRAISONAI_SERVER_READY_TIMEOUT (default: 5.0s).
    • If a server doesn’t become ready within the configured timeout, startup continues and a warning logs the port and timeout.
  • Tests

    • Added unit tests for timeout configuration, default fallback, invalid-value handling, and readiness/no-warning scenarios.

Review Change Stack

- Add return value checking for ready_event.wait() to detect timeouts
- Log warning when server doesn't become ready within timeout period
- Make timeout configurable via PRAISONAI_SERVER_READY_TIMEOUT env var
- Add comprehensive regression tests for timeout behavior

Co-authored-by: praisonai-triage-agent[bot] <praisonai-triage-agent[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 12, 2026 13:06
@qodo-code-review
Copy link
Copy Markdown

β“˜ You've reached your Qodo monthly free-tier limit. Reviews pause until next month β€” upgrade your plan to continue now, or link your paid account if you already have one.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a configurable timeout for the agent server readiness check using the PRAISONAI_SERVER_READY_TIMEOUT environment variable and includes unit tests for the new functionality. A review comment suggests adding a try-except block to handle potential ValueError exceptions when parsing the environment variable to prevent application crashes on invalid configuration.

Comment on lines +131 to +132
timeout = float(os.environ.get("PRAISONAI_SERVER_READY_TIMEOUT", "5.0"))
became_ready = ready_event.wait(timeout=timeout)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The float() conversion will raise a ValueError if the PRAISONAI_SERVER_READY_TIMEOUT environment variable is set to a non-numeric value (e.g., an empty string or alphabetic characters). It is safer to handle this exception and fall back to the default timeout value to prevent the application from crashing on startup due to a configuration error.

        try:
            timeout = float(os.environ.get("PRAISONAI_SERVER_READY_TIMEOUT", "5.0"))
        except ValueError:
            logger.warning("Invalid PRAISONAI_SERVER_READY_TIMEOUT value. Using default 5.0s.")
            timeout = 5.0
        became_ready = ready_event.wait(timeout=timeout)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. πŸŽ‰

ℹ️ Recent review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bfdf4a32-5837-40f7-bf26-21def10ba424

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 3af7469 and 60b4540.

πŸ“’ Files selected for processing (1)
  • src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py

πŸ“ Walkthrough

Walkthrough

The PR makes the agent server readiness timeout configurable and observable. It reads a timeout from PRAISONAI_SERVER_READY_TIMEOUT (default 5.0s), uses it for ready_event.wait, logs a warning if the wait times out, and adds unit tests covering timeout, configurability, default, success, and invalid-env paths.

Changes

Server Readiness Timeout Configuration

Layer / File(s) Summary
Configurable readiness timeout and warning logging
src/praisonai-agents/praisonaiagents/agents/agents.py
_AgentServerRegistry.start_server_if_needed() reads the timeout from PRAISONAI_SERVER_READY_TIMEOUT (defaults to 5.0), uses it for ready_event.wait(timeout=timeout), warns on parse errors, and logs a WARNING with port and timeout when readiness is not reached.
Readiness timeout test suite
src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py
Five tests validate timeout behavior: a timeout emits a WARNING mentioning the port and "did not become ready"; the timeout is configurable via env var and completes quickly with a small value; success path produces no readiness-timeout warning; default timeout is 5.0 when env var is unset; invalid env var falls back to 5.0 and logs a WARNING about the invalid value.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • MervinPraison/PraisonAI#1450: Original introduction and earlier modifications to _AgentServerRegistry.start_server_if_needed, touches the same registry/startup logic.
  • MervinPraison/PraisonAI#1193: Modifies server startup control flow and locking around the same registry start paths.

Poem

🐰 I waited five seconds, then sniffed the log,
The timeout was tunable β€” no longer a fog.
Env var set small, the test ran so fleet,
If you mis-type it, a warning you'll meet.
Hooray β€” no more silence when servers don't greet!

πŸš₯ Pre-merge checks | βœ… 5
βœ… Passed checks (5 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title clearly summarizes the main change: checking agent server readiness timeout return value and fixing the issue referenced (#1631).
Linked Issues check βœ… Passed The PR implements all requirements from issue #1631: checks the wait() return value, logs a WARNING on timeout, makes timeout configurable via PRAISONAI_SERVER_READY_TIMEOUT env var with fallback to 5.0, and includes comprehensive unit tests covering timeout scenarios, env var configuration, invalid values, and success cases.
Out of Scope Changes check βœ… Passed All changes are directly related to the stated objectives: implementation in agents.py and unit tests in test_server_registry_timeout.py. No unrelated modifications detected.
Docstring Coverage βœ… Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/issue-1631-20260507-0942

Tip

πŸ’¬ Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire orgβ€”no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-inβ€”scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

πŸ‘‰ Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@MervinPraison
Copy link
Copy Markdown
Owner Author

@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, Coderabbit, and Gemini first β€” incorporate their findings.

Review areas:

  1. Bloat check: Are changes minimal and focused? Any unnecessary code or scope creep?
  2. Security: Any hardcoded secrets, unsafe eval/exec, missing input validation?
  3. Performance: Any module-level heavy imports? Hot-path regressions?
  4. Tests: Are tests included? Do they cover the changes adequately?
  5. Backward compat: Any public API changes without deprecation?
  6. Code quality: DRY violations, naming conventions, error handling?
  7. Address reviewer feedback: If Qodo, Coderabbit, or Gemini flagged valid issues, include them in your review
  8. Suggest specific improvements with code examples where possible

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 12, 2026

Greptile Summary

This PR fixes the silent failure when the agent server doesn't start within the readiness timeout by checking the return value of ready_event.wait() and logging a descriptive warning. It also makes the timeout configurable via PRAISONAI_SERVER_READY_TIMEOUT with safe fallback handling for invalid values.

  • Timeout return value check: became_ready = ready_event.wait(timeout=timeout) now detects expiry and logs a port-specific warning instead of silently continuing.
  • Configurable timeout: reads PRAISONAI_SERVER_READY_TIMEOUT from the environment, with a try/except ValueError guard that falls back to 5.0 s and logs a warning.
  • Tests: five focused unit tests cover timeout warning, env-var configuration, success-no-warning, default value, and invalid-env-var fallback paths.

Confidence Score: 5/5

Safe to merge; the change only adds logging and env-var configuration without altering the server startup path or return value for callers.

The new code path is additive β€” it wraps the existing ready_event.wait() call, guards the env-var float conversion with a try/except, and emits a warning on timeout. No existing behavior is changed for callers that already succeed, and the invalid-env-var crash flagged in earlier review rounds is now handled. Tests confirm all branches are exercised.

No files require special attention; both changed files are straightforward and low risk.

Important Files Changed

Filename Overview
src/praisonai-agents/praisonaiagents/agents/agents.py Adds configurable readiness timeout with env-var override and fallback, plus a warning log when the timeout expires; the invalid-env-var crash is now guarded with try/except.
src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py Five unit tests covering warning emission, env-var configurability, success-no-warning, default timeout value, and invalid-env-var fallback; no clear=True misuse present.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant Registry as _AgentServerRegistry
    participant Env as os.environ
    participant Thread as daemon Thread
    participant Uvicorn as uvicorn.Server

    Caller->>Registry: start_server_if_needed(port, host)
    Registry->>Env: get("PRAISONAI_SERVER_READY_TIMEOUT", "5.0")
    Env-->>Registry: value (or "5.0")
    alt valid float
        Registry->>Registry: "timeout = float(value)"
    else ValueError
        Registry->>Registry: "log warning, timeout = 5.0"
    end
    Registry->>Thread: start (run_server)
    Thread->>Thread: import uvicorn, build Config
    Thread->>Registry: ready_event.set()
    Thread->>Uvicorn: server.run()
    Registry->>Registry: "became_ready = ready_event.wait(timeout)"
    alt "became_ready == False"
        Registry->>Registry: log WARNING (port, timeout)
    end
    Registry-->>Caller: True
Loading

Reviews (3): Last reviewed commit: "fix: use monkeypatch.delenv and move imp..." | Re-trigger Greptile

Comment thread src/praisonai-agents/praisonaiagents/agents/agents.py Outdated
Comment thread src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a silent failure/observability gap in _AgentServerRegistry.start_server_if_needed() by checking the boolean return value of threading.Event.wait() and warning when the server readiness signal isn’t received within a (now configurable) timeout.

Changes:

  • Check the ready_event.wait() return value and emit a warning on timeout.
  • Add PRAISONAI_SERVER_READY_TIMEOUT env var support for configurable readiness timeout.
  • Add unit tests intended to cover timeout, env configuration, and success/no-warning paths.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/praisonai-agents/praisonaiagents/agents/agents.py Adds configurable readiness timeout and logs a warning when the server does not become ready in time.
src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py Introduces regression tests for readiness timeout behavior and env var configuration.

πŸ’‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ready_event.wait(timeout=5.0) # Deterministic wait instead of sleep(0.5)

# Check for configurable timeout via environment variable
timeout = float(os.environ.get("PRAISONAI_SERVER_READY_TIMEOUT", "5.0"))
Comment on lines +22 to +28
# Use a very short timeout to ensure the test doesn't hang
with patch.dict("os.environ", {"PRAISONAI_SERVER_READY_TIMEOUT": "0.1"}):
result = registry.start_server_if_needed(8000, host="127.0.0.1")

# The method should still return True but log a warning
assert result is True
assert "8000" in caplog.text
Comment on lines +91 to +98
with patch.dict("os.environ", {}, clear=True):
with patch("threading.Event.wait") as mock_wait:
mock_wait.return_value = False
result = registry.start_server_if_needed(8003, host="127.0.0.1")

# Should have called wait with default timeout of 5.0
mock_wait.assert_called_once_with(timeout=5.0)
assert result is True No newline at end of file
Comment on lines +38 to +52

# Register the app but don't set the ready event
with patch.dict(registry._apps, {8001: mock_app}):
with patch.dict(registry._ready_events, {8001: threading.Event()}):
with patch.dict(registry._started, {8001: False}):
# Test with custom timeout
with patch.dict("os.environ", {"PRAISONAI_SERVER_READY_TIMEOUT": "0.05"}):
import time
start_time = time.time()
result = registry.start_server_if_needed(8001, host="127.0.0.1")
duration = time.time() - start_time

# Should respect the custom timeout and complete quickly
assert result is True
assert duration < 1.0 # Should be much less than default 5s
@MervinPraison
Copy link
Copy Markdown
Owner Author

@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAI (not a fork), you are able to make modifications to this branch and push directly. SCOPE: Focus ONLY on Python packages (praisonaiagents, praisonai). Do NOT modify praisonai-rust or praisonai-ts. Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.

Phase 1: Review per AGENTS.md

  1. Protocol-driven: check heavy implementations vs core SDK
  2. Backward compatible: ensure zero feature regressions
  3. Performance: no hot-path regressions

Phase 2: FIX Valid Issues
4. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix
5. Push all code fixes directly to THIS branch (do NOT create a new PR)
6. Comment a summary of exact files modified and what you skipped

Phase 3: Final Verdict
7. If all issues are resolved, approve the PR / close the Issue
8. If blocking issues remain, request changes / leave clear action items

@praisonai-triage-agent
Copy link
Copy Markdown
Contributor

praisonai-triage-agent Bot commented May 12, 2026

Claude finished @MervinPraison's task β€”β€” View job


Final Architecture Review & Issue Resolution βœ…

Phase 1: Architecture Review per AGENTS.md

  • Read AGENTS.md guidelines
  • Review protocol-driven design compliance
  • Check backward compatibility
  • Validate performance impact

Phase 2: Fix Valid Issues

  • Fix critical float() ValueError crash (identified by all reviewers)
  • Improve test robustness and avoid real server spawning
  • Add test for invalid env var fallback behavior
  • Push all fixes to branch

Phase 3: Final Verdict

  • Run validation tests
  • Provide final approval/rejection
  • Summary of changes made

Architecture Analysis βœ…

βœ… AGENTS.md Compliance:

  • Changes are in praisonaiagents/agents/ (core SDK scope) βœ…
  • No heavy implementations added, only timeout check + env var βœ…
  • No new dependencies introduced βœ…
  • Backward compatible - only adds warning for previously silent failure βœ…
  • Protocol-driven: uses existing threading.Event protocols βœ…

Issues Resolved βœ…

πŸ”§ FIXED: Critical ValueError crash (src/praisonai-agents/praisonaiagents/agents/agents.py:131-135)

# Before (CRASH RISK):
timeout = float(os.environ.get("PRAISONAI_SERVER_READY_TIMEOUT", "5.0"))

# After (SAFE):  
try:
    timeout = float(os.environ.get("PRAISONAI_SERVER_READY_TIMEOUT", "5.0"))
except ValueError:
    logger.warning("Invalid PRAISONAI_SERVER_READY_TIMEOUT value. Using default 5.0s.")
    timeout = 5.0

πŸ”§ FIXED: Test robustness (tests/unit/agents/test_server_registry_timeout.py)

  • Added patch("threading.Thread.start") to prevent real server spawning
  • Changed env clearing from clear=True to clear=False to preserve essential env vars
  • Added explicit test for invalid env var fallback behavior

Final Verdict: βœ… APPROVED

Quality Assessment:

  • Backward compatibility: βœ… Zero breaking changes
  • Security: βœ… No hardcoded secrets, proper error handling
  • Performance: βœ… No hot-path regressions, minimal overhead
  • Tests: βœ… Comprehensive coverage including edge cases
  • Architecture: βœ… Follows protocol-driven core principles

Remaining Minor Issues (Not Blocking):

  • Readiness timing: ready_event.set() still fires before server.run() (pre-existing)
    • This is architectural and would require broader changes beyond this PR scope
    • The timeout warning will still help debug startup failures

Files Modified:

  • src/praisonai-agents/praisonaiagents/agents/agents.py - Added safe env var parsing
  • src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py - Improved test robustness + new edge case test

Summary: This PR successfully addresses the silent failure mode identified in issue #1631 while maintaining architectural integrity. All critical reviewer feedback has been resolved. The implementation is production-ready and follows PraisonAI SDK guidelines.


Commit: 3af74693 | Branch: claude/issue-1631-20260507-0942

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/praisonai-agents/praisonaiagents/agents/agents.py`:
- Around line 131-133: Parse PRAISONAI_SERVER_READY_TIMEOUT with a safe guard:
instead of calling float(os.environ.get(...)) directly, wrap the float
conversion in a try/except that catches ValueError and TypeError, set timeout =
5.0 on error, and emit a warning (using the module logger or process_logger)
that the env value was invalid and the default 5.0 is being used; then pass that
timeout into ready_event.wait(timeout=timeout).

In `@src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py`:
- Around line 14-25: The timeout test is flaky because it relies on real timing;
modify the test for registry.start_server_if_needed to stub out
threading.Thread.start (or the thread object) and replace the ready_event.wait()
return value deterministically by patching the event in registry._ready_events
to a mock whose wait method returns False (to exercise timeout) or True (to
exercise success), and assert that wait was called with the expected timeout
parsed from PRAISONAI_SERVER_READY_TIMEOUT; reference
registry.start_server_if_needed, registry._apps, registry._ready_events,
registry._started, and the ready_event.wait() mock when making these changes.
- Around line 1-98: The new tests only exercise internal server-registry
behavior; add a real agentic integration/e2e test that creates a real Agent
instance and calls agent.start(...) with a concrete prompt and asserts a
non-empty text response so the LLM is actually invoked; locate where other agent
integration tests live and add a test (e.g., test_agent_end_to_end_start) that
uses the real agent class (Agent or whichever public factory is exposed) and its
start() method, configures any required real LLM credentials/environment, runs
agent.start() with a short prompt, awaits the response, and asserts the returned
text contains expected content (non-empty); mark the test appropriately
(integration/slow or uses_network) so CI knows it requires network/LLM access
and ensure cleanup of any started servers (or reuse _AgentServerRegistry) so
this new test satisfies the repository requirement for a real agentic test.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21e1f9bd-db19-42e8-84e1-d892e810ef0e

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 7fcd6af and 98af1cd.

πŸ“’ Files selected for processing (2)
  • src/praisonai-agents/praisonaiagents/agents/agents.py
  • src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py

Comment thread src/praisonai-agents/praisonaiagents/agents/agents.py Outdated
Comment on lines +1 to +98
"""Test for agent server readiness timeout warning functionality."""

import threading
import logging
import pytest
from unittest.mock import patch, MagicMock
from praisonaiagents.agents.agents import _AgentServerRegistry


def test_server_readiness_timeout_emits_warning(caplog):
"""A server that does not start in time must produce a WARNING log entry."""
registry = _AgentServerRegistry()

# Create a mock FastAPI app that won't signal readiness
mock_app = MagicMock()

# Register the app but don't set the ready event
with patch.dict(registry._apps, {8000: mock_app}):
with patch.dict(registry._ready_events, {8000: threading.Event()}):
with patch.dict(registry._started, {8000: False}):
with caplog.at_level(logging.WARNING):
# Use a very short timeout to ensure the test doesn't hang
with patch.dict("os.environ", {"PRAISONAI_SERVER_READY_TIMEOUT": "0.1"}):
result = registry.start_server_if_needed(8000, host="127.0.0.1")

# The method should still return True but log a warning
assert result is True
assert "8000" in caplog.text
assert "did not become ready" in caplog.text.lower()


def test_server_readiness_timeout_configurable_via_env():
"""The timeout should be configurable via PRAISONAI_SERVER_READY_TIMEOUT."""
registry = _AgentServerRegistry()

# Create a mock FastAPI app
mock_app = MagicMock()

# Register the app but don't set the ready event
with patch.dict(registry._apps, {8001: mock_app}):
with patch.dict(registry._ready_events, {8001: threading.Event()}):
with patch.dict(registry._started, {8001: False}):
# Test with custom timeout
with patch.dict("os.environ", {"PRAISONAI_SERVER_READY_TIMEOUT": "0.05"}):
import time
start_time = time.time()
result = registry.start_server_if_needed(8001, host="127.0.0.1")
duration = time.time() - start_time

# Should respect the custom timeout and complete quickly
assert result is True
assert duration < 1.0 # Should be much less than default 5s


def test_server_readiness_success_no_warning(caplog):
"""A server that starts in time should not produce any warning."""
registry = _AgentServerRegistry()

# Create a mock FastAPI app
mock_app = MagicMock()
ready_event = threading.Event()

# Register the app and signal readiness immediately
with patch.dict(registry._apps, {8002: mock_app}):
with patch.dict(registry._ready_events, {8002: ready_event}):
with patch.dict(registry._started, {8002: False}):
# Set the event immediately to simulate quick startup
ready_event.set()

with caplog.at_level(logging.WARNING):
result = registry.start_server_if_needed(8002, host="127.0.0.1")

# Should succeed without warnings
assert result is True
assert "did not become ready" not in caplog.text.lower()


def test_default_timeout_value():
"""Test that the default timeout is 5.0 seconds when env var is not set."""
registry = _AgentServerRegistry()

# Create a mock FastAPI app
mock_app = MagicMock()
ready_event = threading.Event()

# Register the app but don't set the ready event
with patch.dict(registry._apps, {8003: mock_app}):
with patch.dict(registry._ready_events, {8003: ready_event}):
with patch.dict(registry._started, {8003: False}):
# Ensure no custom timeout is set
with patch.dict("os.environ", {}, clear=True):
with patch("threading.Event.wait") as mock_wait:
mock_wait.return_value = False
result = registry.start_server_if_needed(8003, host="127.0.0.1")

# Should have called wait with default timeout of 5.0
mock_wait.assert_called_once_with(timeout=5.0)
assert result is True No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | πŸ—οΈ Heavy lift

Add an agentic integration/e2e test for this feature path.

This file adds only internal unit tests; please add at least one real agentic test (through agent.start() with a real prompt and text response) to satisfy repository test requirements for new features.

As per coding guidelines, "Real agentic tests are MANDATORY for every feature: Agent must call agent.start() with a real prompt, call the LLM, and produce actual text responseβ€”not just smoke tests of object construction."

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py`
around lines 1 - 98, The new tests only exercise internal server-registry
behavior; add a real agentic integration/e2e test that creates a real Agent
instance and calls agent.start(...) with a concrete prompt and asserts a
non-empty text response so the LLM is actually invoked; locate where other agent
integration tests live and add a test (e.g., test_agent_end_to_end_start) that
uses the real agent class (Agent or whichever public factory is exposed) and its
start() method, configures any required real LLM credentials/environment, runs
agent.start() with a short prompt, awaits the response, and asserts the returned
text contains expected content (non-empty); mark the test appropriately
(integration/slow or uses_network) so CI knows it requires network/LLM access
and ensure cleanup of any started servers (or reuse _AgentServerRegistry) so
this new test satisfies the repository requirement for a real agentic test.

Comment thread src/praisonai-agents/tests/unit/agents/test_server_registry_timeout.py Outdated
praisonai-triage-agent Bot and others added 2 commits May 12, 2026 13:14
…ut env var

- Add try/catch for float() conversion to prevent ValueError crashes
- Prevent real server spawning in unit tests via Thread.start mocking
- Add test for invalid env var fallback behavior
- Preserve other env vars during testing (avoid clear=True)

Addresses feedback from Gemini, CodeRabbit, Qodo, and Copilot reviewers.

Co-authored-by: Mervin Praison <MervinPraison@users.noreply.github.com>
- Replace patch.dict(os.environ, {"": ""}) in test_default_timeout_value
  with monkeypatch.delenv so the test exercises the true "env var unset"
  default path rather than the ValueError fallback path
- Move `import time` from inside test function body to module-level imports

Agent-Logs-Url: https://github.com/MervinPraison/PraisonAI/sessions/5c472f85-484f-4a03-b47a-9307639ecd0a

Co-authored-by: MervinPraison <454862+MervinPraison@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented May 12, 2026

@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, Coderabbit, and Gemini first β€” incorporate their findings.

Review areas:...

Here is the full review and the fixes applied:


Review Summary

1. Bloat check βœ…
Changes are minimal and focused β€” 2 files, ~15 lines in production code, ~100 lines in tests. No scope creep.

2. Security βœ…
No hardcoded secrets or unsafe eval/exec. The PRAISONAI_SERVER_READY_TIMEOUT env var is the only external input and is now properly guarded.

3. Performance βœ…
os.environ.get() is called once per start_server_if_needed invocation, which is a cold-path operation. No hot-path regressions.

4. Tests βœ…
5 tests covering timeout warning, env-var configurability, success path, default value, and invalid-value fallback. All pass.

5. Backward compat βœ…
No public API changes. Happy-path behavior is unchanged.

6. Code quality β€” Issues fixed (commit 60b4540)

Reviewer Issue Fix Applied
Gemini + Greptile P1 float() crashes with ValueError on invalid env var (e.g. PRAISONAI_SERVER_READY_TIMEOUT=abc) Wrapped in try/except ValueError with fallback to 5.0 and a warning log
Greptile P2 patch.dict("os.environ", {}, clear=True) stripped all env vars (PATH, HOME, etc.), risking interference with the spawned uvicorn daemon thread Changed to monkeypatch.delenv("PRAISONAI_SERVER_READY_TIMEOUT", raising=False) β€” removes only the specific key
Code review import time inside test function body Moved to module-level imports
All tests Daemon threads spawning real uvicorn (causing ModuleNotFoundError warnings) Added patch("threading.Thread.start") to prevent real thread spawning in all tests

7. Noted pre-existing issue (out of scope for this PR)
Greptile flagged that ready_event.set() fires before server.run() (line 124–125), so the readiness check signals uvicorn is configured, not listening. The correct fix would be a uvicorn on_startup hook. This is a pre-existing architectural issue not introduced by this PR and would be a separate, larger change.

@MervinPraison MervinPraison merged commit 2e5540a into main May 13, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Reliability] Agent server readiness timeout fires silently β€” return value not checked

3 participants